<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>RocketMQ长轮询机制详解 | 技术小馆</title>
    <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css">
    <link rel="stylesheet" href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            color: #333;
            line-height: 1.6;
        }
        .article-title {
            font-family: 'Noto Serif SC', serif;
            font-weight: 700;
        }
        .hero-gradient {
            background: linear-gradient(135deg, #6e8efb 0%, #a777e3 100%);
        }
        .code-block {
            background-color: #2d3748;
            border-radius: 0.5rem;
            padding: 1.5rem;
            position: relative;
        }
        .code-header {
            background-color: #1a202c;
            border-top-left-radius: 0.5rem;
            border-top-right-radius: 0.5rem;
            padding: 0.5rem 1rem;
            margin-bottom: -1.5rem;
            margin-left: -1.5rem;
            margin-right: -1.5rem;
            color: #e2e8f0;
            font-family: monospace;
        }
        .code-content {
            color: #e2e8f0;
            overflow-x: auto;
        }
        .card-hover {
            transition: all 0.3s ease;
        }
        .card-hover:hover {
            transform: translateY(-5px);
            box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
        }
        .highlight-box {
            border-left: 4px solid #6e8efb;
            background-color: rgba(110, 142, 251, 0.05);
        }
        .first-letter {
            font-size: 3.5rem;
            line-height: 1;
            float: left;
            margin-right: 0.5rem;
            margin-bottom: -0.5rem;
            color: #6e8efb;
            font-weight: bold;
        }
    </style>
</head>
<body class="bg-gray-50">
    <!-- Hero Section -->
    <section class="hero-gradient text-white py-20 px-4 md:px-0">
        <div class="container mx-auto max-w-5xl flex flex-col md:flex-row items-center">
            <div class="md:w-2/3 md:pr-10">
                <h1 class="article-title text-4xl md:text-5xl leading-tight mb-4">RocketMQ长轮询机制深度解析</h1>
                <p class="text-xl md:text-2xl opacity-90 mb-8">从基础概念到实现原理，全面剖析消息中间件的核心通信机制</p>
                <div class="flex flex-wrap gap-4">
                    <div class="bg-white bg-opacity-20 px-4 py-2 rounded-full flex items-center">
                        <i class="fas fa-code mr-2"></i>
                        <span>消息队列</span>
                    </div>
                    <div class="bg-white bg-opacity-20 px-4 py-2 rounded-full flex items-center">
                        <i class="fas fa-server mr-2"></i>
                        <span>分布式系统</span>
                    </div>
                    <div class="bg-white bg-opacity-20 px-4 py-2 rounded-full flex items-center">
                        <i class="fas fa-bolt mr-2"></i>
                        <span>高性能</span>
                    </div>
                </div>
            </div>
            <div class="md:w-1/3 mt-10 md:mt-0">
                <div class="relative">
                    <div class="absolute inset-0 bg-purple-500 rounded-xl transform rotate-6"></div>
                    <div class="relative bg-white text-gray-800 p-6 rounded-xl shadow-lg">
                        <h3 class="font-bold text-lg mb-2">核心要点</h3>
                        <ul class="space-y-2">
                            <li class="flex items-start">
                                <i class="fas fa-check-circle text-green-500 mt-1 mr-2"></i>
                                <span>减少网络开销</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fas fa-check-circle text-green-500 mt-1 mr-2"></i>
                                <span>提高消息实时性</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fas fa-check-circle text-green-500 mt-1 mr-2"></i>
                                <span>简化实现复杂度</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fas fa-check-circle text-green-500 mt-1 mr-2"></i>
                                <span>增强系统可靠性</span>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Article Content -->
    <article class="container mx-auto max-w-4xl py-12 px-4 md:px-0">
        <!-- Introduction -->
        <section class="mb-16">
            <div class="flex items-center mb-6">
                <div class="h-px bg-gradient-to-r from-purple-500 to-blue-500 w-12 mr-4"></div>
                <h2 class="text-xl font-semibold text-gray-600">引言</h2>
            </div>
            <p class="text-lg leading-relaxed mb-6">
                <span class="first-letter">长</span>轮询是RocketMQ实现消息等待的核心机制，它是一种介于传统轮询和推送模式之间的通信方式，能够有效减少网络开销并保持消息的实时性。在现代分布式系统中，高效的消息传递机制是系统性能的关键所在。本文将深入探讨长轮询的工作原理、实现细节以及在RocketMQ中的具体应用。
            </p>
        </section>

        <!-- Basic Concepts -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-8 flex items-center">
                <div class="w-2 h-8 bg-blue-500 mr-4"></div>
                <span>长轮询的基本概念</span>
            </h2>
            
            <div class="grid md:grid-cols-2 gap-8 mb-12">
                <div class="card-hover bg-white p-6 rounded-xl shadow-md">
                    <div class="flex items-center mb-4">
                        <div class="bg-blue-100 p-2 rounded-full mr-4">
                            <i class="fas fa-info-circle text-blue-500 text-xl"></i>
                        </div>
                        <h3 class="text-xl font-semibold">定义</h3>
                    </div>
                    <ul class="space-y-3 pl-2">
                        <li class="flex">
                            <i class="fas fa-circle text-blue-500 text-xs mt-2 mr-2"></i>
                            <span>长轮询是一种特殊的轮询方式，当服务端没有可用数据时，不会立即返回空结果，而是保持连接一段时间</span>
                        </li>
                        <li class="flex">
                            <i class="fas fa-circle text-blue-500 text-xs mt-2 mr-2"></i>
                            <span>在等待期间，如果有新数据可用，服务端会立即响应</span>
                        </li>
                        <li class="flex">
                            <i class="fas fa-circle text-blue-500 text-xs mt-2 mr-2"></i>
                            <span>如果等待超时仍无数据，则返回空结果，客户端随即发起新的请求</span>
                        </li>
                    </ul>
                </div>
                
                <div class="card-hover bg-white p-6 rounded-xl shadow-md">
                    <div class="flex items-center mb-4">
                        <div class="bg-purple-100 p-2 rounded-full mr-4">
                            <i class="fas fa-exchange-alt text-purple-500 text-xl"></i>
                        </div>
                        <h3 class="text-xl font-semibold">与传统轮询的区别</h3>
                    </div>
                    <div class="highlight-box p-4">
                        <p class="font-medium">传统轮询：</p>
                        <p class="mb-3">客户端定期发送请求，无论服务端是否有新数据都会立即响应</p>
                        <p class="font-medium">长轮询：</p>
                        <p>服务端在无数据时挂起请求，有数据时才响应，减少了无效请求</p>
                    </div>
                </div>
            </div>
            
            <div class="card-hover bg-white p-6 rounded-xl shadow-md mb-8">
                <div class="flex items-center mb-4">
                    <div class="bg-green-100 p-2 rounded-full mr-4">
                        <i class="fas fa-arrows-alt-h text-green-500 text-xl"></i>
                    </div>
                    <h3 class="text-xl font-semibold">与推送模式的区别</h3>
                </div>
                <div class="grid md:grid-cols-2 gap-6">
                    <div>
                        <h4 class="font-semibold text-lg text-green-600 mb-2">推送模式</h4>
                        <ul class="space-y-2">
                            <li class="flex items-start">
                                <i class="fas fa-arrow-right text-green-500 mt-1 mr-2"></i>
                                <span>服务端主动将数据发送给客户端</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fas fa-plug text-green-500 mt-1 mr-2"></i>
                                <span>需要维护长连接</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fas fa-shield-alt text-green-500 mt-1 mr-2"></i>
                                <span>实现复杂度高</span>
                            </li>
                        </ul>
                    </div>
                    <div>
                        <h4 class="font-semibold text-lg text-blue-600 mb-2">长轮询</h4>
                        <ul class="space-y-2">
                            <li class="flex items-start">
                                <i class="fas fa-arrow-left text-blue-500 mt-1 mr-2"></i>
                                <span>仍由客户端发起请求</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fas fa-clock text-blue-500 mt-1 mr-2"></i>
                                <span>服务端控制响应时机</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fas fa-balance-scale text-blue-500 mt-1 mr-2"></i>
                                <span>兼顾了实时性和可靠性</span>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
            
            <!-- Mermaid Diagram -->
            <div class="bg-white p-6 rounded-xl shadow-md mb-8">
                <h3 class="text-xl font-semibold mb-4 flex items-center">
                    <i class="fas fa-project-diagram text-purple-500 mr-2"></i>
                    <span>长轮询流程示意图</span>
                </h3>
                <div class="mermaid">
                    sequenceDiagram
                        participant C as 客户端
                        participant S as 服务端
                        C->>S: 发送拉取请求
                        alt 有可用消息
                            S->>C: 立即返回消息
                        else 无可用消息
                            S-->>C: 保持连接(等待)
                            loop 检查新消息
                                S->>S: 检查新消息
                            end
                            alt 超时前有新消息
                                S->>C: 返回新消息
                            else 超时无消息
                                S->>C: 返回空响应
                            end
                        end
                        C->>S: 发起新请求
                </div>
            </div>
        </section>

        <!-- RocketMQ Implementation -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-8 flex items-center">
                <div class="w-2 h-8 bg-purple-500 mr-4"></div>
                <span>RocketMQ中的长轮询实现</span>
            </h2>
            
            <div class="mb-8">
                <h3 class="text-2xl font-semibold mb-4 text-gray-800">实现原理</h3>
                <div class="bg-white p-6 rounded-xl shadow-md">
                    <ul class="space-y-4">
                        <li class="flex items-start">
                            <div class="bg-blue-500 text-white rounded-full w-6 h-6 flex items-center justify-center mr-3 flex-shrink-0">1</div>
                            <span>消费者通过PullConsumer向Broker发送拉取请求</span>
                        </li>
                        <li class="flex items-start">
                            <div class="bg-blue-500 text-white rounded-full w-6 h-6 flex items-center justify-center mr-3 flex-shrink-0">2</div>
                            <span>如果Broker有可消费的消息，立即返回</span>
                        </li>
                        <li class="flex items-start">
                            <div class="bg-blue-500 text-white rounded-full w-6 h-6 flex items-center justify-center mr-3 flex-shrink-0">3</div>
                            <span>如果没有新消息，Broker会挂起请求，不立即返回</span>
                        </li>
                        <li class="flex items-start">
                            <div class="bg-blue-500 text-white rounded-full w-6 h-6 flex items-center justify-center mr-3 flex-shrink-0">4</div>
                            <span>Broker会在有新消息到达或等待超时时响应请求</span>
                        </li>
                    </ul>
                </div>
            </div>
            
            <div class="grid md:grid-cols-2 gap-8 mb-8">
                <div>
                    <h3 class="text-2xl font-semibold mb-4 text-gray-800">关键参数</h3>
                    <div class="bg-white p-6 rounded-xl shadow-md">
                        <ul class="space-y-4">
                            <li>
                                <h4 class="font-medium text-blue-600">brokerSuspendMaxTimeMillis</h4>
                                <p class="text-sm text-gray-600">Broker挂起请求的最大时间，默认为15秒</p>
                            </li>
                            <li>
                                <h4 class="font-medium text-blue-600">consumerTimeoutMillisWhenSuspend</h4>
                                <p class="text-sm text-gray-600">消费者等待Broker响应的超时时间，默认为30秒</p>
                            </li>
                            <li>
                                <h4 class="font-medium text-blue-600">pullInterval</h4>
                                <p class="text-sm text-gray-600">消费者两次拉取请求的间隔时间，默认为0毫秒</p>
                            </li>
                        </ul>
                    </div>
                </div>
                
                <div>
                    <h3 class="text-2xl font-semibold mb-4 text-gray-800">PullRequestHoldService</h3>
                    <div class="bg-white p-6 rounded-xl shadow-md">
                        <ul class="space-y-4">
                            <li class="flex items-start">
                                <i class="fas fa-tasks text-purple-500 mt-1 mr-2"></i>
                                <span>Broker中专门处理挂起的拉取请求的服务</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fas fa-table text-purple-500 mt-1 mr-2"></i>
                                <span>维护一个按照Topic和QueueId组织的请求映射表</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fas fa-bell text-purple-500 mt-1 mr-2"></i>
                                <span>定期检查是否有新消息到达，如果有则通知对应的请求</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fas fa-clock text-purple-500 mt-1 mr-2"></i>
                                <span>处理请求超时，确保请求不会无限期挂起</span>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
            
            <!-- Code Examples -->
            <div class="mb-8">
                <h3 class="text-2xl font-semibold mb-4 text-gray-800">代码实现</h3>
                
                <div class="grid md:grid-cols-2 gap-6">
                    <div class="code-block">
                        <div class="code-header">
                            <i class="fas fa-user mr-2"></i>消费者端
                        </div>
                        <div class="code-content">
                            <pre><code>// 设置拉取间隔和超时时间
DefaultMQPullConsumer consumer = new DefaultMQPullConsumer("group_name");
consumer.setPullTimeDelayMillsWhenException(1000);
consumer.setConsumerTimeoutMillisWhenSuspend(30000);

// 拉取消息
PullResult pullResult = consumer.pullBlockIfNotFound(
    messageQueue,
    subExpression,
    offset,
    maxNums
);</code></pre>
                        </div>
                    </div>
                    
                    <div class="code-block">
                        <div class="code-header">
                            <i class="fas fa-server mr-2"></i>Broker端
                        </div>
                        <div class="code-content">
                            <pre><code>// PullMessageProcessor.java中的处理逻辑
if (hasSuspendFlag) {
    long pollingTimeMills = suspendTimeoutMillisLong;
    if (!this.brokerController.getBrokerConfig().isLongPollingEnable()) {
        pollingTimeMills = 0;
    }
    
    String topic = requestHeader.getTopic();
    long offset = requestHeader.getQueueOffset();
    int queueId = requestHeader.getQueueId();
    PullRequest pullRequest = new PullRequest(
        request,
        channel,
        pollingTimeMills,
        this.brokerController.getMessageStore().now(),
        offset,
        subscriptionData,
        messageFilter
    );
    
    this.brokerController.getPullRequestHoldService()
        .suspendPullRequest(topic, queueId, pullRequest);
    return null;
}</code></pre>
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- Advantages -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-8 flex items-center">
                <div class="w-2 h-8 bg-green-500 mr-4"></div>
                <span>长轮询的优势</span>
            </h2>
            
            <div class="grid md:grid-cols-2 gap-8">
                <div class="card-hover bg-white p-6 rounded-xl shadow-md">
                    <div class="flex items-center mb-4">
                        <div class="bg-green-100 p-2 rounded-full mr-4">
                            <i class="fas fa-network-wired text-green-500 text-xl"></i>
                        </div>
                        <h3 class="text-xl font-semibold">降低网络开销</h3>
                    </div>
                    <ul class="space-y-3">
                        <li class="flex items-start">
                            <i class="fas fa-check text-green-500 mt-1 mr-2"></i>
                            <span>减少了无效的轮询请求</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check text-green-500 mt-1 mr-2"></i>
                            <span>避免了频繁的连接建立和断开</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check text-green-500 mt-1 mr-2"></i>
                            <span>节省了网络带宽和服务器资源</span>
                        </li>
                    </ul>
                </div>
                
                <div class="card-hover bg-white p-6 rounded-xl shadow-md">
                    <div class="flex items-center mb-4">
                        <div class="bg-blue-100 p-2 rounded-full mr-4">
                            <i class="fas fa-stopwatch text-blue-500 text-xl"></i>
                        </div>
                        <h3 class="text-xl font-semibold">提高实时性</h3>
                    </div>
                    <ul class="space-y-3">
                        <li class="flex items-start">
                            <i class="fas fa-check text-blue-500 mt-1 mr-2"></i>
                            <span>新消息到达时能够立即响应</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check text-blue-500 mt-1 mr-2"></i>
                            <span>相比固定间隔的轮询，减少了消息延迟</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check text-blue-500 mt-1 mr-2"></i>
                            <span>在低负载情况下接近推送模式的实时性</span>
                        </li>
                    </ul>
                </div>
                
                <div class="card-hover bg-white p-6 rounded-xl shadow-md">
                    <div class="flex items-center mb-4">
                        <div class="bg-purple-100 p-2 rounded-full mr-4">
                            <i class="fas fa-cogs text-purple-500 text-xl"></i>
                        </div>
                        <h3 class="text-xl font-semibold">简化实现</h3>
                    </div>
                    <ul class="space-y-3">
                        <li class="flex items-start">
                            <i class="fas fa-check text-purple-500 mt-1 mr-2"></i>
                            <span>不需要维护复杂的长连接和状态管理</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check text-purple-500 mt-1 mr-2"></i>
                            <span>基于HTTP/TCP的请求-响应模型，实现简单</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check text-purple-500 mt-1 mr-2"></i>
                            <span>对防火墙和代理服务器友好</span>
                        </li>
                    </ul>
                </div>
                
                <div class="card-hover bg-white p-6 rounded-xl shadow-md">
                    <div class="flex items-center mb-4">
                        <div class="bg-indigo-100 p-2 rounded-full mr-4">
                            <i class="fas fa-shield-alt text-indigo-500 text-xl"></i>
                        </div>
                        <h3 class="text-xl font-semibold">提高可靠性</h3>
                    </div>
                    <ul class="space-y-3">
                        <li class="flex items-start">
                            <i class="fas fa-check text-indigo-500 mt-1 mr-2"></i>
                            <span>客户端主动发起请求，避免了服务端推送可能的消息丢失</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check text-indigo-500 mt-1 mr-2"></i>
                            <span>客户端可以控制请求频率，防止过载</span>
                        </li>
                        <li class="flex items-start">
                            <i class="fas fa-check text-indigo-500 mt-1 mr-2"></i>
                            <span>服务端故障时，客户端可以感知并采取措施</span>
                        </li>
                    </ul>
                </div>
            </div>
        </section>

        <!-- Message Pull Strategies -->
        <section>
            <h2 class="text-3xl font-bold mb-8 flex items-center">
                <div class="w-2 h-8 bg-indigo-500 mr-4"></div>
                <span>消息拉取的等待策略</span>
            </h2>
            
            <div class="mb-8">
                <h3 class="text-2xl font-semibold mb-4 text-gray-800">拉取模式分类</h3>
                <div class="grid md:grid-cols-3 gap-6">
                    <div class="card-hover bg-white p-6 rounded-xl shadow-md">
                        <h4 class="font-semibold text-lg text-blue-600 mb-2 flex items-center">
                            <i class="fas fa-sync-alt mr-2"></i>同步拉取
                        </h4>
                        <ul class="space-y-2 text-sm">
                            <li class="flex items-start">
                                <i class="fas fa-circle text-xs text-blue-500 mt-1 mr-2"></i>
                                <span>消费者发送拉取请求后，阻塞等待Broker响应</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fas fa-circle text-xs text-blue-500 mt-1 mr-2"></i>
                                <span>适用于对消息处理顺序有严格要求的场景</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fas fa-circle text-xs text-blue-500 mt-1 mr-2"></i>
                                <span>实现方法：调用<code class="bg-gray-100 px-1 rounded">pullBlockIfNotFound</code>方法</span>
                            </li>
                        </ul>
                    </div>
                    
                    <div class="card-hover bg-white p-6 rounded-xl shadow-md">
                        <h4 class="font-semibold text-lg text-purple-600 mb-2 flex items-center">
                            <i class="fas fa-random mr-2"></i>异步拉取
                        </h4>
                        <ul class="space-y-2 text-sm">
                            <li class="flex items-start">
                                <i class="fas fa-circle text-xs text-purple-500 mt-1 mr-2"></i>
                                <span>消费者发送拉取请求后，不阻塞等待，而是通过回调处理响应</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fas fa-circle text-xs text-purple-500 mt-1 mr-2"></i>
                                <span>适用于高吞吐量场景</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fas fa-circle text-xs text-purple-500 mt-1 mr-2"></i>
                                <span>实现方法：调用<code class="bg-gray-100 px-1 rounded">pullAsync</code>方法并提供回调函数</span>
                            </li>
                        </ul>
                    </div>
                    
                    <div class="card-hover bg-white p-6 rounded-xl shadow-md">
                        <h4 class="font-semibold text-lg text-green-600 mb-2 flex items-center">
                            <i class="fas fa-stream mr-2"></i>流式拉取
                        </h4>
                        <ul class="space-y-2 text-sm">
                            <li class="flex items-start">
                                <i class="fas fa-circle text-xs text-green-500 mt-1 mr-2"></i>
                                <span>在异步拉取的基础上，维护一个拉取请求流水线</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fas fa-circle text-xs text-green-500 mt-1 mr-2"></i>
                                <span>确保始终有一定数量的拉取请求在处理中</span>
                            </li>
                            <li class="flex items-start">
                                <i class="fas fa-circle text-xs text-green-500 mt-1 mr-2"></i>
                                <span>适用于超高吞吐量场景</span>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
            
            <div class="mb-8">
                <h3 class="text-2xl font-semibold mb-4 text-gray-800">等待策略实现</h3>
                
                <div class="bg-white p-6 rounded-xl shadow-md mb-6">
                    <h4 class="font-semibold text-lg text-blue-600 mb-3 flex items-center">
                        <i class="fas fa-sort-numeric-up mr-2"></i>基于偏移量的等待
                    </h4>
                    <div class="code-block">
                        <div class="code-header">
                            <i class="fas fa-code mr-2"></i>代码示例
                        </div>
                        <div class="code-content">
                            <pre><code>// 消费者端实现
long nextOffset = consumer.fetchConsumeOffset(messageQueue, true);
PullResult pullResult = consumer.pull(
    messageQueue,
    subExpression,
    nextOffset,
    maxNums
);

// 根据拉取结果处理
switch (pullResult.getPullStatus()) {
    case FOUND:
        // 处理消息
        processMessages(pullResult.getMsgFoundList());
        // 更新偏移量
        nextOffset = pullResult.getNextBeginOffset();
        consumer.updateConsumeOffset(messageQueue, nextOffset);
        break;
    case NO_NEW_MSG:
        // 没有新消息，等待一段时间再拉取
        Thread.sleep(pullInterval);
        break;
    case NO_MATCHED_MSG:
        // 没有匹配的消息，更新偏移量后继续
        nextOffset = pullResult.getNextBeginOffset();
        consumer.updateConsumeOffset(messageQueue, nextOffset);
        break;
    case OFFSET_ILLEGAL:
        // 偏移量非法，重置偏移量
        nextOffset = pullResult.getNextBeginOffset();
        consumer.updateConsumeOffset(messageQueue, nextOffset);
        break;
    default:
        break;
}</code></pre>
                        </div>
                    </div>
                    <div class="mt-4 text-sm text-gray-600">
                        <p>消费者记录每个队列的消费偏移量，拉取请求指定从特定偏移量开始获取消息，Broker根据偏移量判断是否有新消息可消费。</p>
                    </div>
                </div>
                
                <div class="grid md:grid-cols-2 gap-6">
                    <div class="bg-white p-6 rounded-xl shadow-md">
                        <h4 class="font-semibold text-lg text-purple-600 mb-3 flex items-center">
                            <i class="fas fa-clock mr-2"></i>基于时间的等待
                        </h4>
                        <div class="code-block">
                            <div class="code-content">
                                <pre><code>// 设置从一小时前开始消费
consumer.setConsumeFromWhere(
    ConsumeFromWhere.CONSUME_FROM_TIMESTAMP);
consumer.setConsumeTimestamp(UtilAll.timeMillisToHumanString3(
    System.currentTimeMillis() - 3600 * 1000));</code></pre>
                            </div>
                        </div>
                        <div class="mt-4 text-sm text-gray-600">
                            <p>消费者可以指定从特定时间点开始消费，Broker根据消息存储时间判断是否返回，适用于消息回溯或重新消费场景。</p>
                        </div>
                    </div>
                    
                    <div class="bg-white p-6 rounded-xl shadow-md">
                        <h4 class="font-semibold text-lg text-green-600 mb-3 flex items-center">
                            <i class="fas fa-filter mr-2"></i>基于过滤的等待
                        </h4>
                        <div class="code-block">
                            <div class="code-content">
                                <pre><code>// 使用Tag过滤
consumer.subscribe("TopicTest", "TagA || TagB");

// 使用SQL92过滤
consumer.subscribe("TopicTest", 
    MessageSelector.bySql("a between 0 and 3"));</code></pre>
                            </div>
                        </div>
                        <div class="mt-4 text-sm text-gray-600">
                            <p>消费者指定消息过滤条件（Tag或SQL92表达式），Broker只返回符合过滤条件的消息，如果没有符合条件的消息，则等待。</p>
                        </div>
                    </div>
                </div>
            </div>
        </section>
    </article>

    <!-- Footer -->
    <footer class="bg-gray-900 text-white py-12">
        <div class="container mx-auto max-w-4xl px-4 text-center">
            <h3 class="text-xl font-semibold mb-4">技术小馆</h3>
            <a href="http://www.yuque.com/jtostring" class="text-blue-400 hover:text-blue-300 transition-colors">
                <i class="fas fa-globe mr-2"></i>http://www.yuque.com/jtostring
            </a>
            <div class="mt-6 text-gray-400 text-sm">
                © 2023 技术小馆 - 探索技术之美
            </div>
        </div>
    </footer>

    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'dark',
            flowchart: {
                useMaxWidth: true,
                htmlLabels: true,
                curve: 'basis'
            }
        });
    </script>
</body>
</html>